/*************************************************
* @file    	buffer-queue.h
* @author 	dralee
* @version	v1.0
* @date			2021-12-02
* @brief		环形缓冲区队列，适合用于usart/dma等接收
**************************************************/
#ifndef __BUFFER_QUEUE_H
#define __BUFFER_QUEUE_H

#include "stm32f10x.h"
#include <string.h>
#include <stdio.h>

#define QUEUE_NODE_NUM				(2)								// 缓冲队列大小（有多少个缓冲区）需要为2的幂
#define QUEUE_NODE_DATA_LEN		(2*1024)					// 单个接收缓冲区大小

#define QUEUE_DATA_TYPE				ESP_USART_FRAME		// 队列主体数据类型
#define DATA_QUEUE_LOG				QUEUE_DEBUG				// 队列调试输出
#define DATA_QUEUE_LOG_ARRAY	QUEUE_DEBUG_ARRAY	// 调试输出数组

// 数据主体
typedef struct
{
	char *head; 	// 缓冲区头指针
	uint16_t len;	// 接收到数据长度
} ESP_USART_FRAME;

// 队列结构
typedef struct
{
	int size; 	// 缓冲区大小
	int read;		// 读指针
	int write; 	// 写指针
	int read_using; 	// 正在读取缓冲区指针
	int write_using;	// 正在写入缓冲区指针
	QUEUE_DATA_TYPE *elems[QUEUE_NODE_NUM]; // 缓冲区地址
} QueueBuffer;

extern QueueBuffer bq_queue;

#define QUEUE_DEBUG_ON				1
#define QUEUE_DEBUG_ARRAY_ON	1

#define QUEUE_INFO(fmt,arg...)					printf("<<-QUEUE-INFO->> "fmt"\n", ##arg)
#define QUEUE_ERROR(fmt,arg...)					printf("<<-QUEUE-ERROR->> "fmt"\n", ##arg)
#define QUEUE_DEBUG(fmt,arg...)					do{\
																					if(QUEUE_DEBUG_ON)\
																						printf("<<-QUEUE-DEBUG->> [%d]"fmt"\n",__LINE__, ##arg);\
																				}while(0)

#define QUEUE_DEBUG_ARRAY(array, num)		do{\
																						int32_t i;\
																						uint8_t *arr = array;\
																						if(QUEUE_DEBUG_ARRAY_ON)\
																						{\
																							printf("<<-QUEUE-DEBUG-ARRAY->>\n");\
																							for(i = 0; i < (num); i++)\
																							{\
																								printf("%02x   ", (arr)[i]);\
																								if((i + 1) % 10 == 0)\
																								{\
																									printf("\n");\
																								}\
																							}\
																							printf("\n");\
																						}\
																					}while(0)

// 队列状态信息
#define bqPrint(q)				DATA_QUEUE_LOG("size=0x%x, read=%d, write=%d\n", q.size, q.read, q.write);\
													DATA_QUEUE_LOG("size=0x%x, read_using=%d, write_using=%d\n", q.size, q.read_using, q.write_using);

QUEUE_DATA_TYPE* bqWrite(QueueBuffer *q);
QUEUE_DATA_TYPE* bqRead(QueueBuffer *q);
void bqReadFinish(QueueBuffer *q);
void bqWriteFinish(QueueBuffer *q);
QUEUE_DATA_TYPE* bqWriteUsing(QueueBuffer *q);
int bqIsFull(QueueBuffer *q);
int bqIsEmpty(QueueBuffer *q);

void bq_queue_init(void);
void bq_pull_data(void);
void bq_push_data(char *src_data, uint16_t src_len);
																					
#endif //end __BUFFER_QUEUE_H
